package com.ukefu.webim.web.handler.admin;

import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIONamespace;
import com.ukefu.core.UKDataContext;
import com.ukefu.util.Menu;
import com.ukefu.util.UKTools;
import com.ukefu.util.client.NettyClients;
import com.ukefu.util.client.UCKeFuClient;
import com.ukefu.util.es.SearchTools;
import com.ukefu.webim.service.acd.ServiceQuene;
import com.ukefu.webim.service.cache.CacheHelper;
import com.ukefu.webim.service.impl.CallOutQuene;
import com.ukefu.webim.service.repository.OnlineUserRepository;
import com.ukefu.webim.service.repository.SysDicRepository;
import com.ukefu.webim.service.repository.UserRepository;
import com.ukefu.webim.util.OnlineUserUtils;
import com.ukefu.webim.web.handler.Handler;
import com.ukefu.webim.web.model.IMClient;
import com.ukefu.webim.web.model.SysDic;
import com.ukefu.webim.web.model.User;

@Controller
public class AdminController extends Handler{

	@Autowired
	private UserRepository userRes;
	
	@Autowired
	private OnlineUserRepository onlineUserRes;
	
	@Autowired
	private SysDicRepository sysDicRes ;
	
	@Autowired
	private ThreadPoolTaskExecutor taskExecutor ;
	
    @RequestMapping("/admin")
    public ModelAndView index(ModelMap map ,HttpServletRequest request) {
    	ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
        User user = super.getUser(request) ;
        view.addObject("agentStatusReport",ServiceQuene.getAgentReport(user.getOrgi())) ;
		view.addObject("agentStatus",CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), user.getOrgi())) ;
        
		return view;
    }
    
    
    private void aggValues(ModelMap map , HttpServletRequest request){
    	map.put("onlineUserCache", CacheHelper.getOnlineUserCacheBean().getSize()) ;
    	map.put("onlineUserClients", OnlineUserUtils.webIMClients.size()) ;
    	map.put("chatClients", NettyClients.getInstance().size()) ;
    	
    	map.put("agentClients", NettyClients.getInstance().getAgentSize()) ;
    	map.put("callCenterClients", NettyClients.getInstance().getCallCenterSize()) ;
    	
    	map.put("systemCaches", CacheHelper.getSystemCacheBean().getSize()) ;
    	
    	map.put("pool", taskExecutor.getActiveCount()) ;
    	
		map.put("agentReport", ServiceQuene.getAgentReport(super.getOrgi(request))) ;
		
		map.put("agents",getAgent(request).size()) ;

		map.put("inviteResult", UKTools.getWebIMInviteResult(onlineUserRes.findByOrgiAndAgentnoAndCreatetimeRange(super.getOrgi(request), super.getUser(request).getId() , UKTools.getStartTime() , UKTools.getEndTime()))) ;
		
		map.put("agentUserCount", onlineUserRes.countByAgentForAgentUser(super.getOrgi(request), UKDataContext.AgentUserStatusEnum.INSERVICE.toString(),super.getUser(request).getId() , UKTools.getStartTime() , UKTools.getEndTime())) ;
		
		map.put("agentServicesCount", onlineUserRes.countByAgentForAgentUser(super.getOrgi(request), UKDataContext.AgentUserStatusEnum.END.toString(),super.getUser(request).getId() , UKTools.getStartTime() , UKTools.getEndTime())) ;
		
		map.put("agentServicesAvg", onlineUserRes.countByAgentForAvagTime(super.getOrgi(request), UKDataContext.AgentUserStatusEnum.END.toString(),super.getUser(request).getId() , UKTools.getStartTime() , UKTools.getEndTime())) ;
        
		SearchRequestBuilder searchRequestBuilder = UKDataContext.getTemplet().getClient().prepareSearch(UKDataContext.SYSTEM_INDEX).setTypes(UKDataContext.EsTable.UK_USEREVENT.toString());
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
		boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
		boolQueryBuilder.must(rangeQuery("createtime").from(UKTools.getLast30Day().getTime()).to(UKTools.getEndTime().getTime()));
		searchRequestBuilder.setQuery(boolQueryBuilder);
		AggregationBuilder<?> builder =  AggregationBuilders.terms("createdate").field("createdate").order(Terms.Order.term(true));
		builder.subAggregation(AggregationBuilders.terms("id").field("id"));
		builder.subAggregation(AggregationBuilders.cardinality("ip").field("ip"));
		searchRequestBuilder.addAggregation(builder).setSize(0).setFrom(0);
		List<Object> findAllPageAggResult = SearchTools.findAllPageAggResult(searchRequestBuilder,new PageRequest(0, 1), UKDataContext.EsTable.UK_USEREVENT.toString());
		//接入站的访问统计
		map.put("webInviteReport", findAllPageAggResult) ;
		
		//>统计:IP/PV
		if(findAllPageAggResult != null && findAllPageAggResult.size() > 0) {
			map.put("webIMReport", findAllPageAggResult.get(0)) ;
		}
		
		searchRequestBuilder = UKDataContext.getTemplet().getClient().prepareSearch(UKDataContext.SYSTEM_INDEX).setTypes(UKDataContext.EsTable.UK_ONLINEUSER.toString());
		boolQueryBuilder = new BoolQueryBuilder();
		boolQueryBuilder.must(termQuery("orgi" , super.getOrgi(request))) ;
		boolQueryBuilder.must(termQuery("status" , UKDataContext.OnlineUserOperatorStatus.ONLINE.toString())) ;
		searchRequestBuilder.setQuery(boolQueryBuilder);
		AggregationBuilder<?> aggBuilder =  AggregationBuilders.terms("invitestatus").field("invitestatus");
		searchRequestBuilder.addAggregation(aggBuilder).setSize(0).setFrom(0);;
		List<Object> findWebIMInviteStatus = SearchTools.findAllPageAggResultOnlineUser(searchRequestBuilder,new PageRequest(0, 1), UKDataContext.EsTable.UK_ONLINEUSER.toString());
		if(findWebIMInviteStatus != null && !findWebIMInviteStatus.isEmpty()) {
			map.put("webIMInvite",findWebIMInviteStatus.get(0));
		}
		
		map.put("agentConsultReport", UKTools.getWebIMDataAgg(onlineUserRes.findByOrgiAndCreatetimeRangeForAgent(super.getOrgi(request), UKTools.getLast30Day(), UKTools.getEndTime()))) ;
		
		map.put("clentConsultReport", UKTools.getWebIMDataAgg(onlineUserRes.findByOrgiAndCreatetimeRangeForClient(super.getOrgi(request), UKTools.getLast30Day(), UKTools.getEndTime() , UKDataContext.ChannelTypeEnum.WEBIM.toString()))) ;
		
		map.put("browserConsultReport", UKTools.getWebIMDataAgg(onlineUserRes.findByOrgiAndCreatetimeRangeForBrowser(super.getOrgi(request), UKTools.getLast30Day(), UKTools.getEndTime(), UKDataContext.ChannelTypeEnum.WEBIM.toString()))) ;
	}
    private List<User> getAgent(HttpServletRequest request){
		//获取当前产品or租户坐席数
    	List<User> userList = new ArrayList<>();
		if(super.isEnabletneant()) {
			userList = userRes.findByOrgidAndAgentAndDatastatus(super.getOrgid(request), true, false);
		}else {
			 userList = userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true, false);
		}
    	return userList.isEmpty()?new ArrayList<User>():userList;
	}
    
    @RequestMapping("/admin/content")
    @Menu(type = "admin" , subtype = "content")
    public ModelAndView content(ModelMap map , HttpServletRequest request) {
    	aggValues(map, request);
    	return request(super.createAdminTempletResponse("/admin/content"));
    }
    
    @RequestMapping("/admin/clients")
    @Menu(type = "admin" , subtype = "content", admin = true)
    public ModelAndView clients(ModelMap map , HttpServletRequest request , @Valid String type, @Valid String id) {
    	if(UKDataContext.model.get("callcenter")!=null) {
	    	SocketIONamespace callcenternamespace = (SocketIONamespace) UKDataContext.getContext().getBean("callCenterNamespace") ;
	    	if(callcenternamespace!=null) {
	    		Collection<SocketIOClient> callcenterClients = callcenternamespace.getAllClients() ;
	    		List<UCKeFuClient> callcenterClientsList = new ArrayList<UCKeFuClient>();
	    		for(SocketIOClient client : callcenterClients) {
	    			if(!client.getSessionId().toString().equals(id)) {
	    				callcenterClientsList.add(new UCKeFuClient(client.getSessionId().toString() , (String) client.get("name") ,  (String) client.get("time"), client.getRemoteAddress().toString(), client.getHandshakeData().getSingleUrlParam("userid"), client.getHandshakeData().getSingleUrlParam("extention"),!client.isChannelOpen())) ;
	    			}
	    		}
	    		map.addAttribute("callcenterClients", callcenterClientsList) ;
	    		map.put("callcenterNamespaceClients", callcenterClients.size()) ;
	     	}
    	}
    	
    	SocketIONamespace agentNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("agentNamespace") ;
    	if(agentNamespace!=null) {
     		Collection<SocketIOClient> clients = agentNamespace.getAllClients() ;
     		List<UCKeFuClient> agentClientsList = new ArrayList<UCKeFuClient>();
     		for(SocketIOClient client : clients) {
     			if(!client.getSessionId().toString().equals(id)) {
     				agentClientsList.add(new UCKeFuClient(client.getSessionId().toString() , (String) client.get("name") ,  (String) client.get("time"), client.getRemoteAddress().toString(), client.getHandshakeData().getSingleUrlParam("userid"), client.getHandshakeData().getSingleUrlParam("extention"),!client.isChannelOpen())) ;
     			}
    		}
    		map.addAttribute("agentClientsList", agentClientsList) ;
    		map.put("agentNamespaceClients", clients.size()) ;
     	}
    	
    	SocketIONamespace aiimNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("aiimNamespace") ;
    	if(aiimNamespace!=null) {
     		Collection<SocketIOClient> clients = aiimNamespace.getAllClients() ;
     		List<UCKeFuClient> aiClientsList = new ArrayList<UCKeFuClient>();
     		for(SocketIOClient client : clients) {
     			if(!client.getSessionId().toString().equals(id)) {
     				IMClient im = client.get("im") ;
     				if(im!=null) {
     					aiClientsList.add(new UCKeFuClient(client.getSessionId().toString() , im.getNickname(),  im.getDate(), client.getRemoteAddress().toString(), im.getUser(), im.getAppid(),!client.isChannelOpen())) ;
     				}
     			}
    		}
    		map.addAttribute("aiClientsList", aiClientsList) ;
    		map.put("aiimNamespaceClients", clients.size()) ;
     	}
    	
    	SocketIONamespace imNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("imNamespace") ;
    	if(imNamespace!=null) {
     		Collection<SocketIOClient> clients = imNamespace.getAllClients() ;
     		List<UCKeFuClient> imClientsList = new ArrayList<UCKeFuClient>();
     		for(SocketIOClient client : clients) {
     			if(!client.getSessionId().toString().equals(id)) {
     				IMClient im = client.get("im") ;
     				if(im!=null) {
     					imClientsList.add(new UCKeFuClient(client.getSessionId().toString() , im.getNickname() ,  im.getDate(), client.getRemoteAddress().toString(), client.getHandshakeData().getSingleUrlParam("userid"), im.getAppid(),!client.isChannelOpen())) ;
     				}
     			}
    		}
    		map.addAttribute("imClientsList", imClientsList) ;
    		map.put("imNamespaceClients", clients.size()) ;
     	}
    	
     	map.put("chatClients", NettyClients.getInstance().size()) ;
    	map.put("agentClients", NettyClients.getInstance().getAgentSize()) ;
    	map.put("callCenterClients", NettyClients.getInstance().getCallCenterSize()) ;
    	map.put("allUsers", UKDataContext.users.values()) ;
    	map.put("robotCount", CallOutQuene.getRobotToolsCount()) ;
    	map.put("aiUserCount", CallOutQuene.getAiUserCount()) ;
    	
    	map.put("robotStat", CallOutQuene.getRobotToolsStat()) ;
    	map.put("aiUserStat", CallOutQuene.getAiUserStat()) ;
    	
    	map.put("callCenterStat", CallOutQuene.getCallCenterStat()) ;
    	map.put("callOutStat", CallOutQuene.getCallOutNameStat()) ;
    	return request(super.createAdminTempletResponse("/admin/system/monitor/index"));
    }
    
    @RequestMapping("/admin/clients/remove")
    @Menu(type = "admin" , subtype = "content" , admin = true)
    public ModelAndView removeclient(ModelMap map , HttpServletRequest request , @Valid String type ,@Valid String id ,@Valid String userid) {
    	if(!StringUtils.isBlank(type) && type.equals("agent")) {
    		SocketIONamespace agentNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("agentNamespace") ;
    		Collection<SocketIOClient> clients = agentNamespace.getAllClients() ;
    		for(SocketIOClient client : clients) {
    			if(client.getSessionId().toString().equals(id)) {
    				client.disconnect();
    				NettyClients.getInstance().removeAgentEventClient(userid, id);
    				break ;
    			}
    		}
    	}else if(!StringUtils.isBlank(type) && type.equals("callcenter")) {
    		SocketIONamespace agentNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("callCenterNamespace") ;
    		Collection<SocketIOClient> clients = agentNamespace.getAllClients() ;
    		for(SocketIOClient client : clients) {
    			if(client.getSessionId().toString().equals(id)) {
    				client.disconnect();
    				NettyClients.getInstance().removeAgentEventClient(userid, id);
    				break ;
    			}
    		}
    	}else if(!StringUtils.isBlank(type) && type.equals("ai")) {
    		SocketIONamespace aiNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("aiimNamespace") ;
    		Collection<SocketIOClient> clients = aiNamespace.getAllClients() ;
    		for(SocketIOClient client : clients) {
    			if(client.getSessionId().toString().equals(id)) {
    				client.disconnect();
    				NettyClients.getInstance().removeIMEventClient(userid, id);
    				break ;
    			}
    		}
    	}else if(!StringUtils.isBlank(type) && type.equals("im")) {
    		SocketIONamespace imNamespace = (SocketIONamespace) UKDataContext.getContext().getBean("imNamespace") ;
    		Collection<SocketIOClient> clients = imNamespace.getAllClients() ;
    		for(SocketIOClient client : clients) {
    			if(client.getSessionId().toString().equals(id)) {
    				client.disconnect();
    				NettyClients.getInstance().removeIMEventClient(userid, id);
    				break ;
    			}
    		}
    	}
    	return clients(map, request, type , id);
    }
    
    @RequestMapping("/admin/user/remove")
    @Menu(type = "admin" , subtype = "content" , admin = true)
    public ModelAndView removeuser(ModelMap map , HttpServletRequest request , @Valid String type ,@Valid String id ,@Valid String userid) {
    	if(!StringUtils.isBlank(id)) {
    		HttpSession session = UKDataContext.sessions.get(id) ;
    		if(session!=null) {
    			session.invalidate();
    			
    			UKDataContext.sessions.remove(session.getId());
            	UKDataContext.users.remove(session.getId());
    		}
    	}
    	return clients(map, request, type , id);
    }

    @RequestMapping("/admin/auth/infoacq")
    @Menu(type = "admin" , subtype = "infoacq" , access= false , admin = true)
    public ModelAndView infoacq(ModelMap map , HttpServletRequest request) {
    	String inacq = (String) request.getSession().getAttribute(UKDataContext.UKEFU_SYSTEM_INFOACQ) ;
    	if(!StringUtils.isBlank(inacq)){
    		request.getSession().removeAttribute(UKDataContext.UKEFU_SYSTEM_INFOACQ);
    	}else{
    		request.getSession().setAttribute(UKDataContext.UKEFU_SYSTEM_INFOACQ , "true");
    	}
    	return request(super.createRequestPageTempletResponse("redirect:/"));
    }
    
    @RequestMapping("/admin/auth/event")
    @Menu(type = "admin" , subtype = "authevent")
    public ModelAndView authevent(ModelMap map , HttpServletRequest request , @Valid String title , @Valid String url , @Valid String iconstr, @Valid String icontext) {
    	map.addAttribute("title", title) ;
    	map.addAttribute("url", url) ;
    	if(!StringUtils.isBlank(iconstr) && !StringUtils.isBlank(icontext)){
    		map.addAttribute("iconstr", iconstr.replaceAll(icontext, "&#x"+UKTools.string2HexString(icontext)+";")) ;
    	}
    	return request(super.createRequestPageTempletResponse("/admin/system/auth/event"));
    }
    
    @RequestMapping("/admin/auth/save")
    @Menu(type = "admin" , subtype = "authsave")
    public ModelAndView authsave(ModelMap map , HttpServletRequest request , @Valid String title , @Valid SysDic dic) {
    	SysDic sysDic = sysDicRes.findByCode(UKDataContext.UKEFU_SYSTEM_AUTH_DIC) ;
    	boolean newdic = false ;
    	if(sysDic!=null && !StringUtils.isBlank(dic.getName())){
    		if(!StringUtils.isBlank(dic.getParentid())){
    			if(dic.getParentid().equals("0")){
    				dic.setParentid(sysDic.getId());
    				newdic = true ;
    			}else{
    				List<SysDic> dicList = sysDicRes.findByDicidOrderBySortindexAsc(sysDic.getId()) ;
    				for(SysDic temp : dicList){
    					if(temp.getCode().equals(dic.getParentid()) || temp.getName().equals(dic.getParentid())){
    						dic.setParentid(temp.getId());
    						newdic = true ;
    					}
    				}
    			}
    		}
    		if(newdic){
    			dic.setCreater(super.getUser(request).getId());
    			dic.setCreatetime(new Date());
    			dic.setCtype("auth");
    			dic.setDicid(sysDic.getId());
    			sysDicRes.save(dic) ;
    		}
    	}
    	return request(super.createRequestPageTempletResponse("/public/success"));
    }

}